{extend name="user/base" /} {block name="main"}
<script src="__CDN__/static/js/captcha.js"></script>
<div id="app">
  <el-row justify="center">
    <el-col :span="16" :xs="24">
      <div v-if="memberCenter.state.open" class="login-box">
        <div class="login-title" v-if="state.form.tab == 'login'">
          {:__('Login')}
        </div>
        <div class="login-title" v-else>{:__('Register')}</div>
        <el-form
          ref="formRef"
          @keyup.enter="onSubmitPre"
          :rules="rules"
          :model="state.form"
        >
          <!-- 注册验证方式 -->
          <el-form-item v-if="state.form.tab == 'register'">
            <el-radio-group size="large" v-model="state.form.registerType">
              <el-radio
                class="register-verification-radio"
                value="email"
                :disabled="!state.accountVerificationType.includes('email')"
                border
              >
                通过邮箱注册
              </el-radio>
              <!-- <el-radio
                class="register-verification-radio"
                value="mobile"
                :disabled="!state.accountVerificationType.includes('mobile')"
                border
              >
                通过手机号注册
              </el-radio> -->
            </el-radio-group>
          </el-form-item>

          <!-- 登录注册用户名 -->
          <el-form-item prop="username">
            <el-input
              v-model="state.form.username"
              :placeholder="state.form.tab == 'register'? '请输入用户名': '请输入账号'"
              :clearable="true"
              size="large"
            ></el-input>
          </el-form-item>

          <!-- 登录注册密码 -->
          <el-form-item prop="password">
            <el-input
              v-model="state.form.password"
              :placeholder="'请输入密码'"
              type="password"
              show-password
              size="large"
            ></el-input>
          </el-form-item>

          <!-- 注册手机号 -->
          <el-form-item
            v-if="state.form.tab == 'register' && state.form.registerType == 'mobile'"
            prop="mobile"
          >
            <el-input
              v-model="state.form.mobile"
              :placeholder="'请输入密码'"
              :clearable="true"
              size="large"
            ></el-input>
          </el-form-item>

          <!-- 注册邮箱 -->
          <el-form-item
            v-if="state.form.tab == 'register' && state.form.registerType == 'email'"
            prop="email"
          >
            <el-input
              v-model="state.form.email"
              :placeholder="'请输入邮箱'"
              :clearable="true"
              size="large"
            ></el-input>
          </el-form-item>

          <!-- 注册验证码 -->
          <el-form-item v-if="state.form.tab == 'register'" prop="captcha">
            <el-row class="w100">
              <el-col :span="16">
                <el-input
                  size="large"
                  v-model="state.form.captcha"
                  :placeholder="'请输入验证码'"
                  autocomplete="off"
                ></el-input>
              </el-col>
              <el-col class="captcha-box" :span="8">
                <el-button
                  size="large"
                  @click="sendRegisterCaptchaPre"
                  :loading="state.sendCaptchaLoading"
                  :disabled="state.codeSendCountdown <= 0 ? false : true"
                  type="primary"
                >
                  {{ state.codeSendCountdown <= 0 ? '发送' :
                  state.codeSendCountdown + '重新发送' }}
                </el-button>
              </el-col>
            </el-row>
          </el-form-item>

          <div
            v-if="state.form.tab != 'register'"
            class="form-footer d-flex justify-content-between align-items-center"
          >
            <el-checkbox
              v-model="state.form.keep"
              :label="'记住我'"
              size="default"
            ></el-checkbox>
            <div
              @click="state.showRetrievePasswordDialog = true"
              class="forgot-password"
              style="cursor: pointer"
            >
              忘记密码
            </div>
          </div>
          <el-form-item class="form-buttons">
            <el-button
              class="login-btn"
              @click="onSubmitPre"
              :loading="state.formLoading"
              round
              type="primary"
              size="large"
            >
              {{state.form.tab=='login'?'登录':'注册' }}
            </el-button>
            <el-button
              v-if="state.form.tab == 'register'"
              @click="switchTab(formRef, 'login')"
              round
              plain
              type="info"
              size="large"
            >
              返回登录
            </el-button>
            <el-button
              v-else
              @click="switchTab(formRef, 'register')"
              round
              plain
              type="info"
              size="large"
            >
              还没有账户？点击注册
            </el-button>
          </el-form-item>
        </el-form>
      </div>
      <el-alert v-else :center="true" :title="'会员中心已禁用'" type="error" />
    </el-col>
  </el-row>

  <el-dialog
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    v-model="state.showRetrievePasswordDialog"
    :title="'重置密码'"
    :width="state.dialogWidth + '%'"
    :draggable="true"
  >
    <div class="retrieve-password-form">
      <el-form
        ref="retrieveFormRef"
        @keyup.enter="onSubmitRetrieve()"
        :rules="retrieveRules"
        :model="state.retrievePasswordForm"
        :label-width="100"
      >
        <el-form-item :label="'重置方式'">
          <el-radio-group v-model="state.retrievePasswordForm.type">
            <el-radio
              value="email"
              :disabled="!state.accountVerificationType.includes('email')"
              border
            >
              通过邮箱
            </el-radio>
            <!-- <el-radio
              value="mobile"
              :disabled="!state.accountVerificationType.includes('mobile')"
              border
            >
              通过手机号
            </el-radio> -->
          </el-radio-group>
        </el-form-item>
        <el-form-item
          prop="account"
          :label="state.retrievePasswordForm.type == 'email' ? '邮箱' :'手机号'"
        >
          <el-input
            v-model="state.retrievePasswordForm.account"
            :placeholder="state.retrievePasswordForm.type == 'email' ? '请输入邮箱' :'请输入手机号'"
            :clearable="true"
          ></el-input>
        </el-form-item>
        <el-form-item prop="captcha" :label="'验证码'">
          <el-row class="w100">
            <el-col :span="16">
              <el-input
                v-model="state.retrievePasswordForm.captcha"
                :placeholder="'请输入验证码'"
                autocomplete="off"
              ></el-input>
            </el-col>
            <el-col class="captcha-box" :span="8">
              <el-button
                @click="sendRetrieveCaptchaPre"
                :loading="state.sendCaptchaLoading"
                :disabled="state.codeSendCountdown <= 0 ? false : true"
                type="primary"
              >
                {{ state.codeSendCountdown <= 0 ? '发送' :
                state.codeSendCountdown + '重新发送' }}
              </el-button>
            </el-col>
          </el-row>
        </el-form-item>
        <el-form-item prop="password" :label="'新密码'">
          <el-input
            v-model="state.retrievePasswordForm.password"
            :placeholder="'请输入新密码'"
            show-password
          ></el-input>
        </el-form-item>
        <el-form-item>
          <el-button @click="state.showRetrievePasswordDialog = false">
            取消
          </el-button>
          <el-button
            :loading="state.submitRetrieveLoading"
            @click="onSubmitRetrieve()"
            type="primary"
          >
            确认
          </el-button>
        </el-form-item>
      </el-form>
    </div>
  </el-dialog>
</div>
<script>
  const App = {
    setup() {
      const { ref, reactive, createVNode, render, resolveComponent } = Vue;
      const formRef = ref(null);
      const retrieveFormRef = ref(null);
      // 获取URL参数
      const urlParams = new URLSearchParams(window.location.search);
      const tabParam = urlParams.get("tab");
      const memberCenter = reactive({
        state: {
          open: true,
        },
      });
      const state = reactive({
        form: {
          tab: tabParam == "register" ? "register" : "login", // 根据URL参数设置初始tab
          email: "",
          mobile: "",
          username: "",
          password: "",
          captcha: "",
          keep: false,
          captchaId: "{$uuid}",
          captchaInfo: "",
          registerType: "email",
        },
        formLoading: false,
        showRetrievePasswordDialog: false,
        retrievePasswordForm: {
          type: "email",
          account: "",
          captcha: "",
          password: "",
        },
        dialogWidth: 36,
        accountVerificationType: [],
        codeSendCountdown: 0,
        submitRetrieveLoading: false,
        sendCaptchaLoading: false,
      });
      function validatorPassword(rule, val, callback) {
        if (!val) {
          return callback();
        }

        if (!/^(?!.*[&<>"'\n\r]).{6,32}$/.test(val)) {
          return callback(new Error("请输入6~32位的密码"));
        }
        return callback();
      }
      const rules = reactive({
        email: [
          { required: true, message: "邮箱不能为空", trigger: "blur" },
          { type: "email", message: "邮箱格式错误", trigger: "blur" },
        ],
        username: [
          { required: true, message: "用户名不能为空", trigger: "blur" },
        ],
        password: [
          { required: true, message: "密码不能为空", trigger: "blur" },
          { validator: validatorPassword, trigger: "blur" },
        ],
        mobile: [
          { type: "required", message: "手机号不能为空", trigger: "blur" },
          { type: "mobile", message: "手机号格式错误", trigger: "blur" },
        ],
        captcha: [{ type: "required", message: "验证码不能为空" }],
      });

      const retrieveRules = reactive({
        account: [{ required: true, message: "账号不能为空", trigger: "blur" }],
        captcha: [
          { required: true, message: "验证码不能为空", trigger: "blur" },
        ],
        password: [
          { required: true, message: "密码不能为空", trigger: "blur" },
          { validator: validatorPassword, trigger: "blur" },
        ],
      });

      const onSubmitPre = () => {
        formRef.value?.validate((valid) => {
          if (!valid) return;

          if (state.form.tab == "login") {
            clickCaptcha(state.form.captchaId, (captchaInfo) =>
              onSubmit(captchaInfo)
            );
          } else {
            onSubmit();
          }
        });
      };

      const onSubmit = (captchaInfo = "") => {
        state.formLoading = true;
        state.form.captchaInfo = captchaInfo;
        checkIn("post", state.form)
          .then((res) => {
            if (res.code == 1) {
              userInfo.dataFill(res.data.userInfo);
              location.href = "{$url}";
            }
          })
          .finally(() => {
            state.formLoading = false;
          });
      };

      const switchTab = (formRef, tab) => {
        state.form.tab = tab;
        if (tab == "register") state.form.username = "";
        if (formRef) formRef.clearValidate();
      };

      function checkIn(method, params) {
        return createAxios({
          url: "/user/checkIn",
          data: params,
          method: method,
        });
      }

      function shortUuid(prefix = "") {
        const time = Date.now();
        const random = Math.floor(Math.random() * 1000000000);
        if (!window.unique) window.unique = 0;
        window.unique++;
        return prefix + "_" + random + window.unique + String(time);
      }

      const sendRegisterCaptchaPre = () => {
        if (state.codeSendCountdown > 0) return;
        formRef.value
          .validateField([state.form.registerType, "username", "password"])
          .then((valid) => {
            if (!valid) return;
            clickCaptcha(state.form.captchaId, (captchaInfo) =>
              sendRegisterCaptcha(captchaInfo)
            );
          });
      };

      const sendRegisterCaptcha = (captchaInfo) => {
        state.sendCaptchaLoading = true;
        const func = state.form.registerType == "email" ? sendEms : sendSms;
        func(state.form[state.form.registerType], "user_register", {
          captchaInfo,
          captchaId: state.form.captchaId,
        })
          .then((res) => {
            if (res.code == 1) startTiming(60);
          })
          .finally(() => {
            state.sendCaptchaLoading = false;
          });
      };

      const sendRetrieveCaptchaPre = () => {
        if (state.codeSendCountdown > 0) return;
        retrieveFormRef.value.validateField("account").then((valid) => {
          if (!valid) return;
          clickCaptcha(state.form.captchaId, (captchaInfo) =>
            sendRetrieveCaptcha(captchaInfo)
          );
        });
      };
      const sendRetrieveCaptcha = (captchaInfo) => {
        state.sendCaptchaLoading = true;
        const func =
          state.retrievePasswordForm.type == "email" ? sendEms : sendSms;
        func(state.retrievePasswordForm.account, "user_retrieve_pwd", {
          captchaInfo,
          captchaId: state.form.captchaId,
        })
          .then((res) => {
            if (res.code == 1) startTiming(60);
          })
          .finally(() => {
            state.sendCaptchaLoading = false;
          });
      };

      const onSubmitRetrieve = () => {
        if (!retrieveFormRef.value) return;
        retrieveFormRef.value.validate((valid) => {
          if (valid) {
            state.submitRetrieveLoading = true;
            createAxios({
              url: "/account/retrievePassword",
              data: state.retrievePasswordForm,
              method: "POST",
            })
              .then((res) => {
                state.submitRetrieveLoading = false;
                if (res.code == 1) {
                  state.showRetrievePasswordDialog = false;
                  endTiming();
                  onResetForm(retrieveFormRef.value);
                  ElementPlus.ElNotification({
                    message: "重置密码成功",
                    type: "success",
                    zIndex: 9999,
                  });
                }
              })
              .catch(() => {
                state.submitRetrieveLoading = false;
              });
          }
        });
      };

      /**
       * 弹出点击验证码
       * @param uuid 开发者自定义的唯一标识
       * @param callback 验证成功的回调，业务接口可通过 captchaInfo 进行二次验证
       * @param options
       */
      const clickCaptcha = (uuid, callback, options = {}) => {
        const component = resolveComponent(Captcha);

        let vnode = createVNode(component, {
          uuid,
          callback,
          ...options,
          key: shortUuid(),
        });

        render(vnode, document.body);
        vnode = null;
      };

      return {
        state,
        rules,
        memberCenter,
        onSubmitPre,
        onSubmitRetrieve,
        switchTab,
        formRef,
        retrieveFormRef,
        sendRegisterCaptchaPre,
        sendRetrieveCaptchaPre,
        retrieveRules,
      };
    },
  };
  const app = Vue.createApp(App);
  app.use(ElementPlus);
  app.mount("#app");
</script>
{/block}
